package user

import (
	"context"
	// "fmt"
	"strconv"
	"strings"
	"time"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/common/resultx"
	"mall/service/backend/common/i18n"
	"mall/service/user/model"
	"mall/service/user/rpc/internal/svc"
	"mall/service/user/rpc/types/user"

	// "github.com/sirupsen/logrus"
	"github.com/volatiletech/null/v8"
	"github.com/zeromicro/go-zero/core/logx"
)

type UpdateProfileLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewUpdateProfileLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateProfileLogic {
	return &UpdateProfileLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *UpdateProfileLogic) UpdateProfile(in *user.UpdateProfileReq) (*user.BaseResp, error) {
	if in.UserId == nil || *in.UserId == 0 {
		return nil, resultx.StatusError(resultx.USER_ID_REQUIRED, "")
	}

	if in.AuthType == nil || len(strings.TrimSpace(*in.AuthType)) == 0 {
		return nil, resultx.StatusError(resultx.USER_AUTH_PARAM_INVALID, "")
	}

	res, err := l.svcCtx.CurrentUser.FindOneNoCache(l.ctx, nil, *in.UserId)
	if err != nil {
		return nil, err
	}

	uid := res.ID
	rel := &model.UserRel{}

	var avatar string
	if len(in.NewMedia) > 0 {
		mediaFilterMap := make(map[string]map[string][]any)
		mediaFilterMap[model.UserAttachmentRelationshipColumns.UserID] = map[string][]any{
			"equalTo": []any{uid},
		}
		mediaFilterMap[model.UserAttachmentRelationshipColumns.Type] = map[string][]any{
			"equalTo": []any{globalkey.UserAttachmentTypeAvatar},
		}
		mediaList, _, err := l.svcCtx.CurrentUser.GetMedia(l.ctx, model.M{}, -1, mediaFilterMap)
		if err != nil {
			return nil, err
		}

		mediaMap := make(map[uint64]*model.UserAttachmentRelationship)
		mediaIdMap := make(map[uint64]*model.UserAttachmentRelationship)
		if len(mediaList) > 0 {
			for _, m := range mediaList {
				mediaMap[m.AttachmentID] = m
				mediaIdMap[m.AttachmentRelationshipID] = m
			}
		}

		for _, v := range in.NewMedia {
			var url string
			if v.Url != nil && len(*v.Url) > 0 { // 最终网址
				url = *v.Url
			}
			if len(url) == 0 && v.Uri != nil && len(*v.Uri) > 0 { // 临时网址
				url = *v.Uri
			}
			if len(url) == 0 {
				continue
			}

			var thumbnail uint8 // 充当 avatar 的 UserAttachmentRelationship
			if len(avatar) == 0 {
				thumbnail = 1
				avatar = url
			}

			if v.Uid != nil && *v.Uid > 0 {
				if media, ok := mediaIdMap[*v.Uid]; ok { // 已存在，修改
					if v.Id != nil && *v.Id > 0 {
						media.AttachmentID = *v.Id
					}
					if v.Uri != nil && len(*v.Uri) > 0 {
						media.AttachmentSource = *v.Uri
					}
					media.AttachmentImageURL = url
					media.AttachmentThumbnail = thumbnail
					if v.Order != nil && *v.Order > 0 {
						media.AttachmentOrder = uint(*v.Order)
					}
					if v.AltText != nil && len(*v.AltText) > 0 {
						media.AttachmentImageAlt = *v.AltText
					}
					if v.Meta != nil && len(*v.Meta) > 0 {
						media.AttachmentImageMeta = *v.Meta
					}
					rel.Media = append(rel.Media, media)
				}
				continue
			}

			if v.Id != nil && *v.Id > 0 {
				if media, ok := mediaMap[*v.Id]; ok { // 已存在，修改
					if v.Uri != nil && len(*v.Uri) > 0 {
						media.AttachmentSource = *v.Uri
					}
					media.AttachmentImageURL = url
					media.AttachmentThumbnail = thumbnail
					if v.Order != nil && *v.Order > 0 {
						media.AttachmentOrder = uint(*v.Order)
					}
					if v.AltText != nil && len(*v.AltText) > 0 {
						media.AttachmentImageAlt = *v.AltText
					}
					if v.Meta != nil && len(*v.Meta) > 0 {
						media.AttachmentImageMeta = *v.Meta
					}
					rel.Media = append(rel.Media, media)
					continue
				}
			}

			var media model.UserAttachmentRelationship
			if v.Id != nil && *v.Id > 0 {
				media.AttachmentID = *v.Id
			}
			media.Type = uint16(globalkey.UserAttachmentTypeAvatar)
			if v.Uri != nil && len(*v.Uri) > 0 {
				media.AttachmentSource = *v.Uri
			}
			media.AttachmentImageURL = url
			media.AttachmentThumbnail = thumbnail
			if v.Order != nil && *v.Order > 0 {
				media.AttachmentOrder = uint(*v.Order)
			}
			if v.AltText != nil && len(*v.AltText) > 0 {
				media.AttachmentImageAlt = *v.AltText
			}
			if v.Meta != nil && len(*v.Meta) > 0 {
				media.AttachmentImageMeta = *v.Meta
			}
			rel.Media = append(rel.Media, &media)
		}
	}

	var birthday time.Time
	var birthdayIsSet bool
	if in.Birthday != nil && len(strings.TrimSpace(*in.Birthday)) > 0 {
		if localTime, err := modelx.ParseLocalDate(strings.TrimSpace(*in.Birthday)); err == nil {
			birthday = localTime
			birthdayIsSet = true
		}
	}
	if in.Nickname != nil || in.Gender != nil || birthdayIsSet || len(avatar) > 0 { // Todo:
		switch strings.TrimSpace(*in.AuthType) {
		case globalkey.UserAuthTypeWechatMini:
			authFilterMap := make(map[string]map[string][]any)
			authFilterMap[model.UserAuthColumns.UserID] = map[string][]any{
				"equalTo": []any{uid},
			}
			authFilterMap[model.UserAuthColumns.PlatformID] = map[string][]any{
				"equalTo": []any{globalkey.ThirdPartyPlatformWechatMini},
			}
			authList, _, err := l.svcCtx.CurrentUser.GetAuthList(l.ctx, model.M{
				"pageSize": uint64(1),
			}, -1, authFilterMap)
			if err != nil {
				return nil, err
			}

			if len(authList) > 0 {
				rel.Auth = authList[0]
				rel.Auth.Status = uint8(globalkey.StatusEnabled)
			} else {
				rel.Auth = &model.UserAuth{
					UserID: uid,
					Status: uint8(globalkey.StatusEnabled),
				}
			}
			if in.Nickname != nil && len(*in.Nickname) > 0 {
				rel.Auth.Nickname = *in.Nickname
			}
			if in.Gender != nil && *in.Gender > 0 {
				rel.Auth.Gender = uint8(*in.Gender)
			}
			if birthdayIsSet {
				rel.Auth.Birthday = null.TimeFrom(birthday)
			}
			if len(avatar) > 0 {
				rel.Auth.Avatar = avatar
			}
		}

		detailFilterMap := make(map[string]map[string][]any)
		detailFilterMap[model.UserDetailColumns.UserID] = map[string][]any{
			"equalTo": []any{uid},
		}
		detailList, _, err := l.svcCtx.CurrentUser.GetDetailList(l.ctx, model.M{
			"pageSize": uint64(1),
		}, -1, detailFilterMap)
		if err != nil {
			return nil, err
		}

		if len(detailList) > 0 {
			rel.Detail = detailList[0]
		} else {
			rel.Detail = &model.UserDetail{
				UserID: uid,
			}
		}
		if in.Nickname != nil && len(*in.Nickname) > 0 {
			rel.Detail.Nickname = *in.Nickname
		}
		if in.Gender != nil && *in.Gender > 0 {
			rel.Detail.Gender = uint8(*in.Gender)
		}
		if birthdayIsSet {
			rel.Detail.Birthday = null.TimeFrom(birthday)
		}
		if len(avatar) > 0 {
			rel.Detail.Avatar = avatar
		}
	}

	if in.BirthdayHidden != nil {
		metaFilterMap := make(map[string]map[string][]any)
		metaFilterMap[model.UserMetumColumns.UserID] = map[string][]any{
			"equalTo": []any{uid},
		}
		metaList, _, err := l.svcCtx.CurrentUser.GetMeta(l.ctx, model.M{}, -1, metaFilterMap)
		if err != nil {
			return nil, err
		}

		metaMap := make(map[uint64]*user.UserMeta)   // 当前 meta 的 map
		privateMetaKeyMap := make(map[string]uint64) // 特殊 meta 的 map(根据key寻找mid)
		if len(metaList) > 0 {
			for _, v := range metaList {
				if len(v.MetaKey) > 0 && v.MetaValue.Valid {
					mid := v.MetaID
					key := v.MetaKey
					val := v.MetaValue.String
					metaMap[mid] = &user.UserMeta{
						Uid:   int64(mid),
						Key:   key,
						Value: val,
					}
					if strings.Contains(",_birthday_hidden,", ","+key+",") {
						privateMetaKeyMap[key] = mid
					}
				}
			}
		}

		birthdayHidden := strconv.FormatInt(int64(*in.BirthdayHidden), 10)
		if mid, ok := privateMetaKeyMap["_birthday_hidden"]; ok {
			if metum, ok := metaMap[mid]; ok {
				if metum.Value == birthdayHidden { // 不变
					// delete(metaMap, mid)
				} else {
					rel.Meta = append(rel.Meta, &model.UserMetum{
						MetaID:    mid,
						MetaKey:   "_birthday_hidden",
						MetaValue: null.StringFrom(birthdayHidden),
					})
				}
			}
		} else {
			rel.Meta = append(rel.Meta, &model.UserMetum{
				MetaKey:   "_birthday_hidden",
				MetaValue: null.StringFrom(birthdayHidden),
			})
		}
	}

	tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
	if err != nil {
		return nil, resultx.StatusError(resultx.DB_ERROR, "")
	}

	err = l.svcCtx.CurrentUser.Update(l.ctx, tx, res, rel)
	if err != nil {
		// logrus.Info(fmt.Sprintf("UpdateProfile err: %+v", err))
		tx.Rollback()
		return nil, err
	}

	tx.Commit()

	return &user.BaseResp{
		Msg: i18n.UpdateSuccess,
	}, nil
}
